package labb3;

import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.*;
import java.util.ArrayList;

/**
 * Creates a panel containing a JList put in a JScrollPane.
 *
 * @author Mikko Puustinen
 * @version 0.1, 2007-okt-14
 */
class MediaListPanel extends JScrollPane implements ChangeListener {
    private final JList mediaList;
    private ArrayList<Media> media;
    private final CenterPanel centerpanel;
    private final GUI gui;
    private final JPopupMenu popupmenu;
    private final JMenuItem addMedia = new JMenuItem("Add...");
    private final JMenuItem editMedia = new JMenuItem("Edit...");
    private final JMenuItem deleteMedia = new JMenuItem("Delete...");
    private final JMenuItem sortList = new JMenuItem("Sort...");

    /**
     * Creates a default MediaListPanel which is added in a JScrollPane.
     *
     * @param gui         reference to the GUI class.
     * @param centerpanel reference to the panel in the center. Used to make it
     *                    possible to make changes of it.
     * @param list        ArrayList used to construct the list.
     *
     * @see javax.swing.JScrollPane
     */
    public MediaListPanel(GUI gui, CenterPanel centerpanel, ArrayList<Media> list) {
        this.gui = gui;
        this.centerpanel = centerpanel;
        JComponent panel = new JPanel();
        panel.setLayout(new BorderLayout(0, 2));

        media = list;
        mediaList = new JList(list.toArray());
        mediaList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        mediaList.addListSelectionListener(new MediaListSelectionListener());
        mediaList.addKeyListener(new ListKeyListener());
        mediaList.setSelectedIndex(0);
        panel.add(mediaList);
        panel.setBackground(Color.BLACK);
        panel.setRequestFocusEnabled(true);

        popupmenu = new JPopupMenu();
        popupmenu.add(addMedia);
        popupmenu.add(editMedia);
        popupmenu.add(sortList);
        popupmenu.add(new JPopupMenu.Separator());
        popupmenu.add(deleteMedia);
        ActionListener pbl = new PopupButtonListener();
        addMedia.addActionListener(pbl);
        editMedia.addActionListener(pbl);
        sortList.addActionListener(pbl);
        deleteMedia.addActionListener(pbl);
        mediaList.addMouseListener(new ListMouseListener());
        setViewportView(panel);
    }

    /**
     * Called when there is some changes made to the list MediaListPanel is
     * listening at.
     *
     * @param list ArrayList used to construct the list.
     */
    public void notifyListChange(ArrayList<Media> list) {
        int index = list.size() - 1;
        media = list;

        mediaList.setListData(list.toArray());
        mediaList.ensureIndexIsVisible(index);
        mediaList.setSelectedIndex(mediaList.getLastVisibleIndex());
    }

    /**
     * Called when there are any updates made to the list MediaListPanel is
     * listening at.
     */
    public void notifyListUpdate() {
        //TODO: maybe do this better?
        centerpanel.updatePanel(media.get(mediaList.getSelectedIndex()));
    }

    /**
     * Returns the Media object of the selected item in the list.
     *
     * @return the Media object selected in the list.
     *
     * @throws IndexOutOfBoundsException if the selected index does not exist in
     *                                   the list.
     */
    public Media getSelectedMedia() throws IndexOutOfBoundsException {
        return media.get(mediaList.getSelectedIndex());
    }

    /**
     * Creates a listener that will be called whenever the user selects another
     * item in the list.
     */
    private class MediaListSelectionListener implements ListSelectionListener {

        /**
         * Called whenever the value of the selection changes.
         *
         * @param e the event that characterizes the change.
         */
        public void valueChanged(ListSelectionEvent e) {
            int index = mediaList.getSelectedIndex();
            if (index < 0)
                index = 0;
            try {
                centerpanel.updatePanel(media.get(index));
            } catch (Exception e1) {
                centerpanel.resetPanel();
            }
        }
    }

    /**
     * Creates a KeyListener
     */
    private class ListKeyListener extends KeyAdapter {
        /**
         * Invoked when a key has been released. See the class description for
         * {@link java.awt.event.KeyEvent} for a definition of a key released
         * event.
         */
        public void keyReleased(KeyEvent e) {
            if (e.getKeyCode() == KeyEvent.VK_DELETE) {
                if (mediaList.getSelectedIndex() < 0)
                    return;
                gui.removeMedia(getSelectedMedia());
            }
        }
    }

    /**
     * Create a MouseListener in the list and show a popup menu with different
     * options.
     */
    private class ListMouseListener extends MouseAdapter {
        public void mouseClicked(MouseEvent me) {
            if (SwingUtilities.isRightMouseButton(me)) {
                mediaList.setSelectedIndex(mediaList.locationToIndex(me.getPoint()));
                if (mediaList.locationToIndex(me.getPoint()) == mediaList.getSelectedIndex()) {
                    editMedia.setEnabled(true);
                    deleteMedia.setEnabled(true);
                } else {
                    editMedia.setEnabled(false);
                    deleteMedia.setEnabled(false);
                }
                popupmenu.show(mediaList, me.getX(), me.getY());
            } else if (SwingUtilities.isLeftMouseButton(me)) {
                int i = me.getClickCount();
                if (i > 1)
                    gui.editMedia();
            }
        }
    }

    /**
     * Create a listener on the items in a JPopUpMenu
     */
    private class PopupButtonListener implements ActionListener {
        /**
         * Invoked when an action occurs.
         */
        public void actionPerformed(ActionEvent e) {
            if (e.getSource() == addMedia) {
                gui.addMedia();
            } else if (e.getSource() == editMedia) {
                gui.editMedia();
            } else if (e.getSource() == deleteMedia) {
                gui.removeMedia();
            } else if (e.getSource() == sortList) {
                gui.sortList();
            }
        }
    }
}
